<template>
  <div id="threeContainer" class="container"></div>
  <ToolButtons></ToolButtons>
  <!-- :domContainer = "containerDom" -->
</template>
<script setup lang="ts">
import * as THREE from 'three';
import { defineComponent, onMounted, ref } from 'vue';
import { OBJLoader } from 'three/examples/jsm/loaders/OBJLoader';
import { MTLLoader } from 'three/examples/jsm/loaders/MTLLoader';
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader';
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls';
import Stats from 'three/examples/jsm/libs/stats.module';
import ToolButtons from './toolsButtons.vue';
import pinia from '../store/index';
import { threeViewStore } from '../store/models/data';
import * as dat from 'dat.gui';

import { EffectComposer } from 'three/examples/jsm/postprocessing/EffectComposer';
import { RenderPass } from 'three/examples/jsm/postprocessing/RenderPass';
import { OutlinePass } from 'three/examples/jsm/postprocessing/OutlinePass';
import { UnrealBloomPass } from 'three/examples/jsm/postprocessing/UnrealBloomPass';

const store = threeViewStore(pinia);
let scene: THREE.Scene;
let camera: THREE.Camera;
const containerDom = ref();
/**加载模型及贴图 */
function LoadModel(obj: any, mtl: any) {
  var objloader = new OBJLoader(); //obj加载器
  var mtlloader = new MTLLoader(); //材质文件加载器
  // 使用 GLTFLoader 加载模型
  const gltfloader = new GLTFLoader();

  //obj的模型会和MaterialCreator包含的材质对应起来

  gltfloader.load(
    '/obj/SYS.glb', // 模型的路径
    function (gltf) {
      // 这个是返回的模型对象
      console.log(gltf, 'gltf.attributes');

      // 获取返回的场景对象
      const model = gltf.scene;

      // 设置模型的位置
      // model.position.set(0, 13, 0);

      // 可以选择缩放模型
      // model.scale.set(1.5, 1.5, 1.5);
      const box = new THREE.Box3().setFromObject(model);
      const center = new THREE.Vector3();
      box.getCenter(center);

      // 移动模型，使其中心对齐到 (0, 0, 0)
      model.position.set(-center.x, -center.y, -center.z);
      model.rotation.set(0, 180, 0); // 重置旋转

      // 添加到场景中
      scene.add(model);

      // 将模型对象存储在 window 对象上，方便后续操作
      window.meshObj = model;

      // 之后可以继续设置 GUI 控制项
      addGui();
    }
  );

  // mtlloader.load(mtl, function (materials) {
  //   // 返回一个包含材质的对象MaterialCreator
  //   console.log(materials);
  //   //obj的模型会和MaterialCreator包含的材质对应起来
  //   objloader.setMaterials(materials);
  //   objloader.load(obj, function (obj) {
  //     console.log(obj, 'obj.attributes');
  //     obj.position.set(0, 13, 0);
  //     // obj.translateY(1.5);
  //     scene.add(obj);//返回的组对象插入场景中
  //     // obj.children[0].scale.set(135, 135, 135);//网格模型缩放
  //     // obj.children[0].scale.set(0.5, 0.5, 5);
  //     window.meshObj = obj;
  //     addGui()
  //   })
  // })
}
function init() {
  scene = new THREE.Scene();
  const axesHelper = new THREE.AxesHelper(10); // 参数是坐标轴长度
  scene.add(axesHelper);
  window.threeScene = scene;
  // LoadModel('/obj/model.obj', '/obj/material.mtl');
  LoadModel('/obj/SYS.glb');

  // LoadModel('/彩色模型/Bk2-CS.obj', '/彩色模型/Bk2-CS.mtl');
  // LoadModel('/彩色模型/XL05-CS.obj', '/彩色模型/XL05-CS.mtl');
  //点光源
  var point = new THREE.PointLight(0xffffff);
  point.position.set(0, 0, 0); //点光源位置
  scene.add(point); //点光源添加到场景中
  //环境光
  var ambient = new THREE.AmbientLight(0xffffff, 1);
  scene.add(ambient);

  /**
   * 相机设置
   */
  var width = window.innerWidth; //窗口宽度
  var height = window.innerHeight; //窗口高度
  var k = width / height; //窗口宽高比
  // var s = 5; //三维场景显示范围控制系数，系数越大，显示的范围越大
  var s = 150;
  var fov = 450;
  window.fov = fov;
  //创建相机对象,,OrthographicCamera--正投影相机
  // camera = new THREE.OrthographicCamera(-s * k, s * k, s, -s, 1, 100);//OrthographicCamera( left, right, top, bottom, near, far )
  // camera = new THREE.OrthographicCamera(-s * k, s * k, s, -s, 1, 1000);
  // camera.position.set(0, 50, 60); //设置相机位置
  // camera.lookAt(scene.position); //设置相机方向(指向的场景对象)
  // window.camera = camera;
  // console.log(k,-s * k, s * k, s, -s,'k---');
  // 使用透视投影相机会导致绘制的点被无限放大，透视投影相机不会
  camera = new THREE.PerspectiveCamera(fov, k, 0.1, 5000); //四个参数后两个参数表示近裁面和远裁面
  camera.position.set(0, 0, -500);
  camera.lookAt(0, 0, -500);

  // 存在疑问，为啥物体在相机视锥体的近裁截面这边而不是视锥体的中间
  scene.add(camera);

  window.camera = camera;

  // 带相机助手的相机，相当于第三视角观测threejs世界，可以观测到threejs的相机和物体
  // const camera1 = new THREE.PerspectiveCamera(fov, k, 0.1, 100);
  // camera1.position.set(0, 0, 10);
  // camera.lookAt(0, 0, 0);
  // let cameraHelper = new THREE.CameraHelper(camera1);
  // scene.add(cameraHelper);
  // window.camera1 = camera1;

  // console.log(cameraHelper, 'camera');
  /**
   * 创建渲染器对象
   */
  var renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });
  renderer.shadowMap.enabled = true; // 显示阴影
  renderer.setClearColor(0x000000, 1); //0x000000   0xff0000
  window.renderer = renderer;
  renderer.setSize(width, height); //设置渲染区域尺寸
  // renderer.setClearColor(0xb9d3ff, 1); //设置背景颜色
  document.getElementById('threeContainer')?.appendChild(renderer.domElement); //body元素中插入canvas对象

  // 引入渲染帧率查看器
  const stats = new Stats();
  document.body.appendChild(stats.domElement);
  stats.setMode(0);
  // 渲染函数
  function render() {
    stats.update();
    renderer.render(scene, camera); //执行渲染操作
    requestAnimationFrame(render); //请求再次执行渲染函数render，渲染下一帧，window的方法大约每16.7ms调用一次requestAnimationFrame()方法指定的函数，实现渲染器渲染方法render()的周期性调用
  }
  render();
  var controls = new OrbitControls(camera, renderer.domElement); //本质改变的是相机的参数，不是场景
  window.controls = controls;

  // 画布跟随窗口变化
  window.onresize = function () {
    renderer.setSize(window.innerWidth, window.innerHeight);
    camera.aspect = window.innerWidth / window.innerHeight;
    camera.updateProjectionMatrix();
  };
  // let AxesHelper = new THREE.AxesHelper(1000);
  // scene.add(AxesHelper);
}
function addGui() {
  const cubeParams = {
    rotationX: window.meshObj.rotation.x, // 控制立方体X轴旋转
    rotationY: window.meshObj.rotation.y, // 控制立方体Y轴旋转
    positionX: window.meshObj.position.x, // 控制立方体X轴位置
    positionY: window.meshObj.position.y, // 控制立方体Y轴位置
    positionZ: window.meshObj.position.z, // 控制立方体Z轴位置
  };

  const gui = new dat.GUI();
  // 控制位置
  gui
    .add(cubeParams, 'positionX', -10, 10, 0.1)
    .name('Position X')
    .onChange((value) => {
      window.meshObj.position.x = value;
    });
  gui
    .add(cubeParams, 'positionY', -10, 10, 0.1)
    .name('Position Y')
    .onChange((value) => {
      window.meshObj.position.y = value;
    });
  gui
    .add(cubeParams, 'positionZ', -10, 10, 0.1)
    .name('Position Z')
    .onChange((value) => {
      window.meshObj.position.z = value;
    });

  // 控制旋转
  gui
    .add(cubeParams, 'rotationX', 0, Math.PI * 2, 0.01)
    .name('Rotation X')
    .onChange((value) => {
      window.meshObj.rotation.x = value;
    });
  gui
    .add(cubeParams, 'rotationY', 0, Math.PI * 2, 0.01)
    .name('Rotation Y')
    .onChange((value) => {
      window.meshObj.rotation.y = value;
    });
}
onMounted(() => {
  init();
  containerDom.value = document.getElementById('threeContainer');
});
</script>

<style scoped>
.container {
  width: 100%;
  height: 100%;
}
</style>
